package com.google.p2pbench;

import android.os.Parcelable;

import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;

/**
 * Generic connectivity abstraction. Includes service discovery, messages (unreliable) and streams.
 */
public interface Connectivity {
  public final static int SHUTDOWN_PREVIOUS = 0;
  public final static int SHUTDOWN_OFF = 1;
  public final static int SHUTDOWN_ON = 2;

  class ConnectivityException extends Exception {
    private static final long serialVersionUID = 1L;

    public ConnectivityException(String msg) {
      super(msg);
    }

    public ConnectivityException(String msg, Throwable throwable) {
      super(msg, throwable);
    }
  }

  // True if supports ByteBuffer (non-stream) message delivery.
  boolean supportsMessages();

  interface Listener {
    void onConnected();

    void onError(ConnectivityException exception);
  }

  boolean connect(Listener listener);

  void shutdown(int mode);

  // Identifies client or service (virtual endpoint).
  interface Peer extends Parcelable {
    // Returns human-readable description.
    String getDescription();
  }

  // Some connectivity layers support broadcast allowing us to skip discovery.

  // Returns null if not supported.
  Peer getBroadcastPeer();

  void setBroadcastService(Service service) throws ConnectivityException;

  void sendMessage(Peer peer, ByteBuffer msg) throws ConnectivityException;

  interface Socket {
    void close();

    boolean isConnected();

    InputStream getInputStream() throws ConnectivityException;

    OutputStream getOutputStream() throws ConnectivityException;
  }

  Socket getSocket(Peer peer) throws ConnectivityException;

  interface Service {
    void onError(ConnectivityException exception);

    void onMessage(Peer peer, ByteBuffer msg);

    void onStream(Peer peer, Socket socket);
  }

  // Returns the Peer which can be passed to other services.
  Peer announce(String serviceType, Service service) throws ConnectivityException;

  void unnannounce(String serviceType, Service service);

  interface Discoverer {
    void onDiscovery(String serviceType, Peer peer);
  }

  void discover(String serviceType, Discoverer listener);

  void stopDiscovery(String serviceType, Discoverer listener);
}

